# -*- coding: utf-8 -*-
# created on 2016/11/10

from sympy import Interval, S, Intersection, oo, FiniteSet, Union
from mathsolver.functions.base.base import BaseFunction
from mathsolver.functions.base.objects import BaseSet, BaseIneqs, BaseIneq, BaseEq
from mathsolver.functions.fangcheng.budengshi import FangChenBuDengShi001
from mathsolver.functions.hanshu.zhiyu import HanShuZhiYu
from mathsolver.functions.hanshu.helper import check_inter


class QuJianBiaoShi(BaseFunction):
    def __init__(self):
        super(QuJianBiaoShi, self).__init__()
        self.op_num_dict = dict()

    def solver(self, *args):
        """区间的表示"""
        if isinstance(args[0], BaseIneqs):
            result = S.Reals
            ineqs_list = args[0].sympify()
            sym = list(args[0].free_symbols())[0]
            for ineq in ineqs_list:
                ineq_list = self.__normalize_ineq(ineq, sym)
                result = Intersection(result, self.__construct_interval(ineq_list))
        elif isinstance(args[0], BaseIneq):
            ineq = args[0].sympify()
            sym = list(args[0].free_symbols())[0]
            ineq_list = self.__normalize_ineq(ineq, sym)
            result = self.__construct_interval(ineq_list)
        elif isinstance(args[0], BaseSet):
            result = S.EmptySet
            sym = args[0].value["var"]
            conditions = args[0].value["conditions"]
            for cond in conditions:
                if "set" in cond:
                    for num in cond['set']:
                        result += FiniteSet(int(num))
                elif 'ineq' in cond:
                    ineq_list = self.__normalize_ineq(cond['ineq'], sym)
                    if ineq_list is None:
                        return self
                    result = Union(result, self.__construct_interval(ineq_list))
                elif "eq" in cond:
                    # eq时表示求值域
                    jiede = HanShuZhiYu().solver(BaseEq(cond['eq']).eq2func(), Interval(-oo, oo))
                    self.steps += jiede.steps
                    self.output.append(jiede.output[0])
                    pass
                else:
                    pass
        self.output.append(result)
        self.label.add("区间的表示")
        return self

    @staticmethod
    def __construct_interval(ineq_list):
        if len(ineq_list) == 5:
            left, right = True, True
            if '=' in ineq_list[1]:
                left = False
            if '=' in ineq_list[3]:
                right = False
            return Interval(ineq_list[0], ineq_list[4], left, right)
        elif len(ineq_list) == 3:
            if ineq_list[1] == '<':
                return Interval(-oo, ineq_list[2], True, True)
            if ineq_list[1] == '<=':
                return Interval(-oo, ineq_list[2], True, False)
            if ineq_list[1] == '>':
                return Interval(ineq_list[2], oo, True, True)
            if ineq_list[1] == '>=':
                return Interval(ineq_list[2], oo, False, True)

    @staticmethod
    def __reverse_op(op):
        if '>' in op:
            return op.replace('>', '<')
        elif '<' in op:
            return op.replace('<', '>')
        return op

    def __normalize_ineq(self, ineq_list, sym):
        """['2', '>', 'x', '>', '-3']==>[-3, '<', 'x', '<', 2], [10, '<', 'x']==>['x', '>', 10]"""
        if isinstance(ineq_list, tuple):
            ineq_list = list(ineq_list)
        if len(ineq_list) == 5:
            if ('<' in ineq_list[1] and '>' in ineq_list[3]) or ('>' in ineq_list[1] and '<' in ineq_list[3]):
                return None
            ineq_list[0], ineq_list[4] = int(ineq_list[0]), int(ineq_list[4])
            if '>' in ineq_list[1] and '>' in ineq_list[3]:
                ineq_list = [ineq_list[4], ineq_list[1].replace('>', '<'), ineq_list[3].replace('>', '<'), ineq_list[0]]
        elif len(ineq_list) == 3:
            if sym == ineq_list[2]:
                ineq_list = [ineq_list[2], self.__reverse_op(ineq_list[1]), int(ineq_list[0])]
            else:
                ineq_list[2] = int(ineq_list[2])
        return ineq_list

    def __add_num_to_op_numlist_dict(self, op, num):
        if op in self.op_num_dict:
            if isinstance(num, list):
                self.op_num_dict[op] += [int(n) for n in num]
            else:
                self.op_num_dict[op].append(int(num))
        else:
            if isinstance(num, list):
                self.op_num_dict[op] = [int(n) for n in num]
            else:
                self.op_num_dict[op] = [int(num)]


class QuJianQiuCan(BaseFunction):
    def solver(self, *args):
        """根据区间定义求参数"""
        interval = check_inter(args[0])
        left_num, right_num, left_op, right_op = interval.args
        jiede = FangChenBuDengShi001().solver(BaseIneq([left_num, '<', right_num]))
        self.output += jiede.output
        self.steps += jiede.steps
        self.label.add("根据区间定义求参数")
        return self


if __name__ == '__main__':
    pass
